package org.example.app.builtin_functions

import java.io.File


fun main() {
    let()
    apply()
    run()
    with_()
    also()
    takeIf()
    takeUnless()
    repeat_()
    use()
}

/**
 * 1. let
 * 用途：可以在对象上执行一段操作，并返回结果。常用于作用域内操作，并返回最终结果。
 * 典型用法：用于链式调用或者防止 null 引发的错误。
 */
fun let() {
    println("----- let -----")
    val result = "Kotlin".let {
        println(it)
        it.length
    }
    println(result)
}

/**
 * 2. apply
 * 用途：类似于 let，但它返回的是对象本身，而不是结果。常用于对象初始化时，链式调用中设置对象的属性。
 * 典型用法：常用于初始化对象或在对象上进行一系列修改。
 */
fun apply() {
    println("----- apply -----")
    val builder = StringBuilder().apply {
        append("Hello ")
        append("World!")
    }
    println(builder.toString())
}

/**
 * 3. run
 * 用途：run 既是作用域函数，也用于执行一段代码块。它的返回值是代码块的返回值，常用于执行复杂的操作并返回结果。
 * 典型用法：可以用来创建对象并执行一段代码。
 */
fun run() {
    println("----- run -----")
    val result = run {
        val x = 2
        val y = 3
        x + y
    }
    println(result)
}

/**
 * 4. with
 * 用途：with 用于作用域函数，但它的返回值是通过对指定对象进行一系列操作来得到的，返回的是最后一行代码的值。适用于对同一对象多次操作的情况。
 * 典型用法：多个操作作用于同一个对象时，可以使用 with 来简化代码。
 */
fun with_() {
    println("----- with -----")
    val builder = StringBuilder().apply {
        append("Kotlin ")
        append("is ")
        append("fun")
    }
    val result = with(builder) {
        append("!")
        length
    }
    println(result)
}

/**
 * 5. also
 * 用途：和 let 类似，但 also 返回的是原始对象本身，通常用于进行一些额外的操作（如调试、日志记录）而不改变对象。
 * 典型用法：常用于在链式调用中做一些副作用操作。
 */

fun also(){
    println("----- also -----")
    val numbers = mutableListOf("one", "two", "three")
    numbers.also {
        println("List before: $numbers")
        numbers.add("five")
    }.add("four")
    println(numbers)
}

/**
 * 6. takeIf 和 takeUnless
 * 用途：用于条件检查。takeIf 在条件成立时返回对象本身，否则返回 null，而 takeUnless 是 takeIf 的反向操作。
 * 典型用法：通常用于过滤操作。
 */
fun takeIf(){
    println("------ takeIf -----")
    val number = 10
    val result = number.takeIf { it > 5 }
    println(result)
}

/**
 * 7. repeat
 * 用途：repeat 是用于执行某个操作的简洁方式，它会重复指定的次数来执行代码块。
 * 典型用法：在循环中用来重复某个操作。
 */
fun takeUnless(){
    println("----- takeUnless -----")
    val number = 10
    val result = number.takeUnless { it > 5 }
    println(result)

}

/**
 * 7. repeat
 * 用途：repeat 是用于执行某个操作的简洁方式，它会重复指定的次数来执行代码块。
 * 典型用法：在循环中用来重复某个操作。
 */
fun repeat_(){
    println("------ repeat -----")
    repeat(3){
        print("$it ")
    }
}

/**
 * use 是一个扩展函数，它主要用于简化资源管理。它的作用是自动关闭 Closeable 对象（例如文件、流、数据库连接等），
 * 即使发生异常也会确保资源被正确释放。这个函数的使用方式类似于 Java 中的 try-with-resources 语句。
 */
fun use(){
    println("------ use -----")
    File("").bufferedReader().use { reader ->
        reader.forEachLine {
            println(it)
        }
    }
}